package com.icebergteam.warfacewidget.news.data;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Date;

import org.json.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.SQLException;
import android.os.StrictMode;
import com.icebergteam.warfacewidget.AppManager;
import com.icebergteam.warfacewidget.WidgetProvider;
import com.icebergteam.warfacewidget.core.LogManager;
import com.icebergteam.warfacewidget.core.Parser;
import com.icebergteam.warfacewidget.core.connection.NetworkManager;
import com.icebergteam.warfacewidget.core.connection.services.RSSFeedService;
import com.icebergteam.warfacewidget.core.utils.ViewUtils;
import com.icebergteam.warfacewidget.data.sql.NewsTable;

public class NewsParser extends Parser  {
	final public static String className = NewsParser.class.getCanonicalName();
	
	
	public NewsParser(boolean restoreKey) {
		super(restoreKey);
	}

	public NewsParser() {
		super();
	}

	@Override
	public int saveData(String url) throws Exception {
		try {
			if (this.isRestoreKey() && AppManager.getDatabase().getNewsTable().getCountCurrentLocale()>0){
				LogManager.LogV(NewsParser.className, LogManager.getExecuteMethodName(),
						"generate restore");
				throw new Exception(WidgetProvider.RESTORE_ACTION); 
			}
			this.setRestoreKey(false);
			StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitAll().build());
			URLConnection con = new URL(url).openConnection();
			LogManager.LogVA(NewsParser.className, url);
			con.setReadTimeout(Parser.TIMEOUT);
			con.setConnectTimeout (Parser.TIMEOUT);
			
			this.doc = Jsoup.parse(con.getInputStream(), "UTF-8", "");
			parseXML(doc, -1);

			this.stateRequest = NewsParser.REQUEST_COMPLETED;
			LogManager.LogV(NewsParser.className,  LogManager.getExecuteMethodName(), url);

		} catch (SocketTimeoutException e) {
			LogManager.LogE(NewsParser.className,  LogManager.getExecuteMethodName(), "timeout");
			e.printStackTrace();
			restore(NewsParser.REQUEST_FAILED | NewsParser.LIST_RESTORED,
										NewsParser.REQUEST_FAILED | NewsParser.LIST_RESTORED);
		} catch (IOException e) {
			LogManager.LogE(NewsParser.className,  LogManager.getExecuteMethodName(), url, e.getMessage());
			e.printStackTrace();
			restore(NewsParser.REQUEST_FAILED | NewsParser.LIST_RESTORED,
								NewsParser.REQUEST_FAILED);
		}catch (SQLException e) {
			LogManager.LogE(NewsParser.className,  LogManager.getExecuteMethodName(), url, e.getMessage());
			e.printStackTrace();
			this.stateRequest = NewsParser.DB_INVALID;
			
		}catch (Exception e) {
			LogManager.LogE(NewsParser.className,  LogManager.getExecuteMethodName(),
					e.getLocalizedMessage());
			
			if (WidgetProvider.RESTORE_ACTION.equals(e.getMessage())) {
				restore(NewsParser.LIST_RESTORED, NewsParser.REQUEST_FAILED);
			}
			else{
				this.stateRequest = (NewsParser.REQUEST_FAILED);
				e.printStackTrace();
			}
		}
		return this.stateRequest;
	}

	@Override
	protected	void  restore(int complete, int failed)	throws Exception {
		try {
			int count = AppManager.getDatabase().getNewsTable().getCountCurrentLocale();
			
			if(count == -1){
				throw new Exception( LogManager.getExecuteMethodName() + " - DB empty");
			}
		
			this.stateRequest = complete;
			LogManager.LogV(NewsParser.className,  LogManager.getExecuteMethodName());
		}catch (SQLException e) {
			e.printStackTrace();
			throw new SQLException(String.format(
					"%s - error = %s",  LogManager.getExecuteMethodName(), e.getMessage()));
		}catch (Exception e1) {
			e1.printStackTrace();
			this.stateRequest = failed;
	
			throw new Exception(String.format(
					"%a - error = %s",  LogManager.getExecuteMethodName(),e1.getMessage()));
		}
	}
	
	@Override
	public ArrayList<NewsItem> parseXML(Document doc, int limit) throws Exception {
		try {
			doc.normalise();
			Elements listItems = doc.select("item");
			ArrayList<NewsItem> newsList = new ArrayList<NewsItem>();
			int index =0;
			for (Element item: listItems) {
				NewsItem tempItem = getItem(item);
				newsList.add(tempItem);
				index++;
				if(limit >= 0 && index == limit) break;
			}
			return newsList;
		} 
		catch (SQLException e) {
			e.printStackTrace();
			throw new SQLException(String.format(
					"%s - doc = %s; error = %s",  LogManager.getExecuteMethodName(), (doc == null) ? doc == null :doc.toString(),
					e.getMessage()));
		}
		catch (Exception e) {
			e.printStackTrace();
			this.stateRequest = NewsParser.XML_INVALID;

			throw new Exception(String.format(
					"%s - doc = %s; error = %s",  LogManager.getExecuteMethodName(), (doc == null) ? doc == null :doc.toString(),
					e.getMessage()));
		}
	}
	
	@Override
	protected NewsItem getItem(org.jsoup.nodes.Element elem) throws Exception {
		NewsItem item = new NewsItem();
		item.setTitle(elem.select("title").first().text());
		item.setDesc(elem.select("description").first().text());
		item.setPubdate(new Date(elem.select("pubDate").first().text()).getTime());
		item.setLink(ViewUtils.fixUrlString(ViewUtils.findTextBeetweenTags("<link />", "<description>", elem.toString())));
		
		String url = item.getLink();
		long newDataNewsItem = item.getPubdate();
		ContentValues dataToInsert = new ContentValues();    
		dataToInsert.put(NewsTable.FIELD_TITLE, item.getTitle());
		dataToInsert.put(NewsTable.FIELD_DESC, item.getDesc());
		dataToInsert.put(NewsTable.FIELD_PUBDATE, newDataNewsItem);
		dataToInsert.put(NewsTable.FIELD_URL, url);
		
		
		dataToInsert.put(NewsTable.FIELD_RSSDOMAIN, NetworkManager.getUri(new RSSFeedService(), false));
		dataToInsert.put(NewsTable.FIELD_CATEGORY_NAME, elem.select("category").first().text());
		dataToInsert.put(NewsTable.FIELD_CATEGORY_DOMAIN, ViewUtils.fixUrlString(elem.select("category").first().attr("domain")));
							
		/*find downloaded news*/
		Cursor newsItemCursor = AppManager.getDatabase().getNewsTable().getNewsByUrl(url);
		newsItemCursor.moveToFirst();
		
		/*check refresh news*/
		if(newsItemCursor!=null && newsItemCursor.getCount()!= 0){
			long oldDataNewsItem = newsItemCursor.getLong(newsItemCursor.getColumnIndex(NewsTable.FIELD_PUBDATE.trim()));
			
			if(oldDataNewsItem != newDataNewsItem){
				dataToInsert.putNull(NewsTable.FIELD_HTML);
				dataToInsert.put(NewsTable.FIELD_READ, false);
			}
			else{
				item.setRead(true);
			}
		}
		else{
			dataToInsert.put(NewsTable.FIELD_READ, false);
		}
		
		AppManager.getDatabase().getNewsTable().updateOrInsert(dataToInsert);
		
		return item;
	}

	@Override
	public Object parseXML(JSONObject doc, int limit) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}
}